﻿using BestHTTP;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

namespace ZL_Framework
{
    /// <summary>
    /// Http网络请求管理器
    /// </summary>
    public class HttpRequestManager : MonoSingleton<HttpRequestManager>
    {
        //private string testGetUrl = "https://api.seniverse.com/v3/weather/now.json?key=la5u6mmcm1lietgh&location=beijing&language=zh-Hans&unit=c";
        #region BestHTTP方式
        /*
         * HttpRequestManager.Instance.BestHttpGet(testGetUrl, callback:(req, response) =>
         * {
         *     LogTool.Instance.Log(response.DataAsText);
         * });
         * 
         */
        public void BestHttpGet(string url, Dictionary<string, object> param = null, Dictionary<string, object> header = null, OnRequestFinishedDelegate callback = null, int connectTimeOut = 5, int timeOut = 5)
        {
            HTTPRequest request = CreateGetRequestUrl(url, param, header, (originalRequest, response) =>
            {
                if (callback != null)
                {
                    LogTool.Instance.Log(response.DataAsText);
                    callback.Invoke(originalRequest, response);
                }
            }, connectTimeOut, timeOut);
            request.Send();
        }

        public void BestHttpPost(string url, Dictionary<string, object> param = null, Dictionary<string, object> header = null, OnRequestFinishedDelegate callback = null, int connectTimeOut = 5, int timeOut = 5)
        {
            HTTPRequest request = CreatePostRequestUrl(url, param, header, (originalRequest, response) =>
            {
                if (callback != null)
                {
                    LogTool.Instance.Log(response.DataAsText);
                    callback.Invoke(originalRequest, response);
                }
            }, connectTimeOut, timeOut);
            request.Send();
        }

        private HTTPRequest CreateGetRequestUrl(string url, Dictionary<string, object> param = null, Dictionary<string, object> header = null, OnRequestFinishedDelegate callback = null, int connectTimeOut = 5, int timeOut = 5)
        {
            StringBuilder paramBuilder = new StringBuilder();
            if (param != null && param.Count > 0)
            {
                paramBuilder.Append(url.Contains("?") ? "&" : "?");
                foreach (KeyValuePair<string, object> kv in param)
                {
                    paramBuilder.Append(kv.Key);
                    paramBuilder.Append("=");
                    paramBuilder.Append(kv.Value.ToString());
                    paramBuilder.Append("&");
                }
            }

            url = url + paramBuilder.ToString().TrimEnd('&');
            LogTool.Instance.Log("BestHTTPGet: " + url);
            HTTPRequest request = new HTTPRequest(new Uri(url), HTTPMethods.Get, callback)
            {
                ConnectTimeout = TimeSpan.FromSeconds(connectTimeOut),
                Timeout = TimeSpan.FromSeconds(timeOut)
            };

            if (header != null && header.Count > 0)
            {
                foreach (KeyValuePair<string, object> kv in header)
                {
                    request.AddHeader(kv.Key, kv.Value.ToString());
                }
            }
            return request;
        }

        private HTTPRequest CreatePostRequestUrl(string url, Dictionary<string, object> param = null, Dictionary<string, object> header = null, OnRequestFinishedDelegate callback = null, int connectTimeOut = 5, int timeOut = 5)
        {
            LogTool.Instance.Log("BestHTTPPost: " + url);
            HTTPRequest request = new HTTPRequest(new Uri(url), HTTPMethods.Post, callback)
            {
                ConnectTimeout = TimeSpan.FromSeconds(connectTimeOut),
                Timeout = TimeSpan.FromSeconds(timeOut)
            };

            if (param != null && param.Count > 0)
            {
                foreach (KeyValuePair<string, object> kv in param)
                {
                    request.AddField(kv.Key, kv.Value.ToString());
                }
            }

            if (header != null && header.Count > 0)
            {
                foreach (KeyValuePair<string, object> kv in header)
                {
                    request.AddHeader(kv.Key, kv.Value.ToString());
                }
            }
            return request;
        }
        #endregion

        #region UnityWebRequest方式
        public void Get(string url, Action<UnityWebRequest> OnResponse)
        {
            StartCoroutine(GetRequest(url, OnResponse));
        }

        public void Post(string url, WWWForm param, Action<UnityWebRequest> OnResponse)
        {
            StartCoroutine(PostRequest(url, param, OnResponse));
        }

        public void GetTexture(string url, Action<Texture2D> OnResponse)
        {
            StartCoroutine(GetTextureRequest(url, OnResponse));
        }

        public void GetAudio(string url, Action<AudioClip> OnResponse, AudioType audioType = AudioType.WAV)
        {
            StartCoroutine(GetAudioRequest(url, OnResponse, audioType));
        }

        public void GetAssetBundle(string url, Action<AssetBundle> OnResponse)
        {
            StartCoroutine(GetAssetBundleRequest(url, OnResponse));
        }

        public void GetFile(string url, string fileName, Action<UnityWebRequest> OnResponse)
        {
            StartCoroutine(GetFileRequest(url, fileName, OnResponse));
        }

        private IEnumerator GetRequest(string url, Action<UnityWebRequest> OnResponse)
        {
            LogTool.Instance.Log("Get: " + url);
            UnityWebRequest webRequest = UnityWebRequest.Get(url);

            yield return webRequest.SendWebRequest();
            if (webRequest.isHttpError || webRequest.isNetworkError)
            {
                LogTool.Instance.Log(webRequest.error);
            }
            else
            {
                OnResponse?.Invoke(webRequest);
                LogTool.Instance.Log(webRequest.downloadHandler.text);
            }
        }

        private IEnumerator PostRequest(string url, WWWForm param, Action<UnityWebRequest> OnResponse)
        {
            LogTool.Instance.Log("Post: " + url);

            UnityWebRequest webRequest = UnityWebRequest.Post(url, param);

            yield return webRequest.SendWebRequest();
            if (webRequest.isHttpError || webRequest.isNetworkError)
            {
                LogTool.Instance.Log(webRequest.error);
            }
            else
            {
                OnResponse?.Invoke(webRequest);
                LogTool.Instance.Log(webRequest.downloadHandler.text);
            }
        }

        private IEnumerator GetTextureRequest(string url, Action<Texture2D> OnResponse)
        {
            LogTool.Instance.Log("Get Texture: " + url);
            UnityWebRequest webRequest = new UnityWebRequest(url);
            DownloadHandlerTexture downloadHandler = new DownloadHandlerTexture(true);
            webRequest.downloadHandler = downloadHandler;
            yield return webRequest.SendWebRequest();
            if (webRequest.isHttpError || webRequest.isNetworkError)
            {
                LogTool.Instance.Log(webRequest.error);
            }
            else
            {
                OnResponse?.Invoke(downloadHandler.texture);
            }
        }

        private IEnumerator GetAudioRequest(string url, Action<AudioClip> OnResponse, AudioType audioType = AudioType.WAV)
        {
            LogTool.Instance.Log("Get Audio: " + url);
            UnityWebRequest webRequest = UnityWebRequestMultimedia.GetAudioClip(url, audioType);
            yield return webRequest.SendWebRequest();
            if (webRequest.isHttpError || webRequest.isNetworkError)
            {
                LogTool.Instance.Log(webRequest.error);
            }
            else
            {
                OnResponse?.Invoke(DownloadHandlerAudioClip.GetContent(webRequest));
            }
        }

        private IEnumerator GetAssetBundleRequest(string url, Action<AssetBundle> OnResponse)
        {
            LogTool.Instance.Log("Get AssetBundle: " + url);
            UnityWebRequest webRequest = new UnityWebRequest(url);
            DownloadHandlerAssetBundle downloadHandler = new DownloadHandlerAssetBundle(webRequest.url, uint.MaxValue);
            webRequest.downloadHandler = downloadHandler;
            yield return webRequest.SendWebRequest();
            if (webRequest.isHttpError || webRequest.isNetworkError)
            {
                LogTool.Instance.Log(webRequest.error);
            }
            else
            {
                OnResponse?.Invoke(downloadHandler.assetBundle);
            }
        }

        private IEnumerator GetFileRequest(string url, string fileName, Action<UnityWebRequest> OnResponse)
        {
            LogTool.Instance.Log("Get AssetBundle: " + url);
            UnityWebRequest webRequest = new UnityWebRequest(url, UnityWebRequest.kHttpVerbGET);
            webRequest.downloadHandler = new DownloadHandlerFile(fileName);
            yield return webRequest.SendWebRequest();
            if (webRequest.isHttpError || webRequest.isNetworkError)
            {
                LogTool.Instance.Log(webRequest.error);
            }
            else
            {
                OnResponse?.Invoke(webRequest);
            }
        }
        #endregion
    }
}